#include "system.h"
#include "mcu.h"
#include "ports.h"
#include "types.h"
#include "gpio.h"


UINT8 xdata g_uart_recv_buffer[UART_RECV_BUF_LENGTH];
UINT8 data g_uart_recv_w_pos = 0;
UINT8 data g_uart_recv_r_pos = 0;
UINT8 data g_uart_recv_size= 0;

UINT8 xdata g_uart_send_buffer[UART_SEND_BUF_LENGTH];
UINT8 data g_uart_send_w_pos = 0;
UINT8 data g_uart_send_r_pos = 0;
UINT8 data g_uart_send_size = 0;


void system_init(void)
{
    mcu_init();
    sys_uart_init(SYS_UART_BAUDRATE_115200);
    sys_uart_start();
}

// timer2 frequence=24500000/count
void sys_timer2_install(UINT16 count)
{
    UINT16 reload_value = 0xFFFF - count;

    TMR2CN  = 0x00;                     // Stop Timer2; Clear TF2;

    SET_BIT(CKCON, BIT_4, 1);                     // Timer2 clocked based on SYSCLK

    TMR2RLH = (UINT8)(reload_value>>8);  // Init reload values
    TMR2RLL = (UINT8)reload_value;

    TMR2H = 0xff;                   // Set to reload immediately
    TMR2L = 0xff;
}

void sys_timer2_start()
{
    ET2     = 1;                        // Enable Timer2 interrupts
    TR2     = 1;                        // Start Timer2
}

void sys_timer2_stop()
{
    ET2     = 0;                        // disable Timer2 interrupts
    TR2     = 0;                        // stop Timer2
}

void sys_timer3_install(UINT16 count)
{
    UINT16 reload_value = 0xFFFF - count;

    TMR3CN  = 0x00;                     // Stop Timer3; Clear TF3;

    SET_BIT(CKCON, BIT_6, 1);                     // Timer2 clocked based on SYSCLK

    TMR3RLH = (UINT8)(reload_value>>8);  // Init reload values
    TMR3RLL = (UINT8)reload_value;

    TMR3H = 0xff;                   // Set to reload immediately
    TMR3L = 0xff;
}
void sys_timer3_start()
{
    //ET3     = 1;                        // Enable Timer3 interrupts
    SET_BIT(EIE1, BIT_7, 1);

    //TR3     = 1;                        // Start Timer3
    SET_BIT(TMR3CN, BIT_2, 1);
}

void sys_timer3_stop()
{
    //ET3     = 0;                        // disable Timer3 interrupts
    SET_BIT(EIE1, BIT_7, 0);

    //TR3     = 0;                        // stop Timer3
    SET_BIT(TMR3CN, BIT_2, 0);
}


void sys_uart_init(SYS_UART_BAUDRATE_T br)
{
    SCON0 = 0x10;                       // SCON0: 8-bit variable bit rate
                                       //        level of STOP bit is ignored
                                       //        RX enabled
                                       //        ninth bits are zeros
                                       //        clear RI0 and TI0 bits
    switch(br)
    {
        case SYS_UART_BAUDRATE_9600:
        {
            TH1 = -(MCU_SYSCLK/9600/2/12);
            CKCON &= ~0x0B;
            break;
        }
        case SYS_UART_BAUDRATE_56000:
        {
            TH1 = -(MCU_SYSCLK/56000/2);
            CKCON |= 0x08;
            break;
        }
        case SYS_UART_BAUDRATE_115200:
        {
            TH1 = -(MCU_SYSCLK/115200/2);
            CKCON |= 0x08;
            break;
        }
        default:
        {
            TH1 = -(MCU_SYSCLK/115200/2);
            CKCON |= 0x08;
        }

    }

    TL1 = TH1;                          // init Timer1
    TMOD &= ~0xf0;                      // TMOD: timer 1 in 8-bit autoreload
    TMOD |=  0x20;
    IP |= 0x10;                         // Make UART high priority

}

void sys_uart_start()
{
    TR1 = 1;                            // START Timer1
    ES0 = 1;                            // Enable UART0 interrupts
}
void sys_uart_stop()
{
    TR1 = 0;                            // STOP Timer1
    ES0 = 0;                            // disable UART0 interrupts
}


void sys_uart_interrupt_handler(void) interrupt 4
{
    if (RI0 == 1)
    {
       RI0 = 0;                           // Clear interrupt flag
       if(g_uart_recv_size < UART_RECV_BUF_LENGTH){
           g_uart_recv_w_pos %= UART_RECV_BUF_LENGTH;
           g_uart_recv_buffer[g_uart_recv_w_pos] = SBUF0;
           ++g_uart_recv_w_pos;
           ++g_uart_recv_size;
       }
    }

    if (TI0 == 1)                   // Check if transmit flag is set
    {
       if( g_uart_send_size>0 ){
            g_uart_send_r_pos %= UART_SEND_BUF_LENGTH;
            SBUF0 = g_uart_send_buffer[g_uart_send_r_pos];
            ++g_uart_send_r_pos;
            g_uart_send_size--;
       }
       if( g_uart_send_size == 0 ){
            TI0 = 0;                // Clear interrupt flag
       }
    }
}

BOOL sys_uart_send_byte(UINT8 sdata)
{
    BOOL res = FALSE;

    SYS_UART_INT_DISABLE;
    if( g_uart_send_size < UART_SEND_BUF_LENGTH ){
        g_uart_send_w_pos %= UART_SEND_BUF_LENGTH;
        g_uart_send_buffer[g_uart_send_w_pos] = sdata;
        ++g_uart_send_w_pos;
        ++g_uart_send_size;
        res = TRUE;
    }
    SYS_UART_INT_ENABLE;

    // tigger send interrupt
    TI0 = 1;

    return res;
}

BOOL  sys_uart_read_byte( UINT8* rdata)
{
    BOOL res = FALSE;

    SYS_UART_INT_DISABLE;
    if( g_uart_recv_size > 0 ){
        g_uart_recv_r_pos %= UART_RECV_BUF_LENGTH;
        *rdata = g_uart_recv_buffer[g_uart_recv_r_pos];
        ++g_uart_recv_r_pos;
        --g_uart_recv_size;
        res = TRUE;
    }
    SYS_UART_INT_ENABLE;

    return res;
}

